package 泛型通配符的有关数据输入;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * <?>：代表任意类型。跟<T>区别很大，不要单纯的以为就是符号不一样。用法差别很大的，两者没有任何关系。
 */
public class Test {
    public static void main(String[] args) {

        /**
         * ArrayList<? extends E> al = new ArrayList<? extends E>();
         * 泛型的限定：
         *      ? extends E:接收E类型或者E的子类型
         *      ? super E:接收E类型或者E的父类型
         *      注意：使用 ?声明的任意类型，都不能直接实例化。都需要靠另外一个类似的字段直接赋值给它
         */
        ArrayList<? extends Object> al = new ArrayList<>();
//        al.add("333");//报错，不能直接往里面添加元素，
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("a");//普通的可以正常添加元素
        list1.add("b");
        list1.add("c");
        //需要另外一个相同类型的字段，直接赋值
        al = list1;
        System.out.println(al);

        //调用print方法
        System.out.println("--------------调用print方法---------------------");
        ArrayList<Object> objects = new ArrayList<>();
        objects.add(new People());
        print(objects);

        //调用print2方法
        System.out.println("--------------调用print2方法---------------------");
        print2(String.class);
        print2(Object.class);


        //调用print3方法
        System.out.println("--------------调用print3方法---------------------");
        print3(Object.class);
        print3(String.class);

    }

    /**
     * List<?> list：使用任意List集合接口类型，作为参数
     *  参数解析：
     *      （1）List表示：List集合接口类型
     *      （2）由于使用了<?>，所以是任意类型的
     * @param list
     */
    public static void print(List<?> list) {
        Iterator<?> iterator = list.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }

    /**
     * Class<?> clazz：使用任意类的字节码文件对象，作为参数
     *  参数解析：
     *      （1）Class表示：类类型（即，这种类型表示字节码文件对象）
     *      （2）由于使用了<?>，所以是任意类型的
     * @param clazz
     */
    public static void print2(Class<?> clazz) {
        String name = clazz.getName();
        System.out.println(name);
    }

    /**
     * Class<T> clazz：也相当于，使用任意类的字节码文件对象，作为参数；
     *                 但是这种方式，需要在方法前面声明 T类型（即，在方法权限修饰符后面，使用<T>）
     *
     *  总结：所以<?>与<T>在一定程度上可以互相替代，但是不能完全互相替代。有些情况只能使用<T>,而不能使用<?>
     * @param clazz
     * @param <T>
     */
    public static <T> void print3(Class<T> clazz) {
        String name = clazz.getName();
        System.out.println(name);
    }

}
